#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include <string>
#include <fstream>
#include <streambuf>
#include <sstream>
#include <cstdlib>
#include <new>
#include <typeinfo>
#include <list>
#include <thread> // std::thread
#include <mutex>  // std::mutex

using namespace std;

class GameObject
{
public:
    virtual void collide(GameObject &otherObject) = 0;
};
class SpaceShip : public GameObject
{
    virtual void collide(GameObject &otherObject);
};
class SpaceStation : public GameObject
{
    virtual void collide(GameObject &otherObject);
};
class Asteroid : public GameObject
{
    virtual void collide(GameObject &otherObject);
};

void checkForCollision(GameObject &object1, GameObject &object2)
{
    if (theyJustCollided(object1, object2))
    {
        processCollision(object1, object2);
    }
    else
    {
    }
}

// if we collide with an object of unknown type, we
// throw an exception of this type:
class CollisionWithUnknownObject
{
public:
    CollisionWithUnknownObject(GameObject &whatWeHit);
};

void SpaceShip::collide(GameObject &otherObject)
{
    const type_info &objectType = typeid(otherObject);
    if (objectType == typeid(SpaceShip))
    {
        SpaceShip &ss = static_cast<SpaceShip &>(otherObject);
        // process a SpaceShip-SpaceShip collision;
    }
    else if (objectType == typeid(SpaceStation))
    {
        SpaceStation &ss =
            static_cast<SpaceStation &>(otherObject);
        // process a SpaceShip-SpaceStation collision;
    }
    else if (objectType == typeid(Asteroid))
    {
        Asteroid &a = static_cast<Asteroid &>(otherObject);
        // process a SpaceShip-Asteroid collision;
    }
    else
    {
        throw CollisionWithUnknownObject(otherObject);
    }
}

class SpaceShip;
// forward declarations
class SpaceStation;
class Asteroid;
class GameObject
{
public:
    virtual void collide(GameObject &otherObject) = 0;
    virtual void collide(SpaceShip &otherObject) = 0;
    virtual void collide(SpaceStation &otherObject) = 0;
    virtual void collide(Asteroid &otherobject) = 0;
};
class SpaceShip : public GameObject
{
public:
    virtual void collide(GameObject &otherObject);
    virtual void collide(SpaceShip &otherObject);
    virtual void collide(SpaceStation &otherObject);
    virtual void collide(Asteroid &otherobject);
};

void SpaceShip::collide(GameObject &otherObject)
{
    otherObject.collide(*this);
}






class GameObject
{
public:
    virtual void collide(GameObject &otherObject) = 0;
};


class SpaceShip : public GameObject
{
public:
    virtual void collide(GameObject &otherObject);
    virtual void hitSpaceShip(SpaceShip &otherObject);
    virtual void hitSpaceStation(SpaceStation &otherObject);
    virtual void hitAsteroid(Asteroid &otherobject);
};


void SpaceShip::hitSpaceShip(SpaceShip &otherObject)
{
    // process a SpaceShip-SpaceShip collision;
}
void SpaceShip::hitSpaceStation(SpaceStation &otherObject)
{
    // process a SpaceShip-SpaceStation collision;
}
void SpaceShip::hitAsteroid(Asteroid &otherObject)
{
    // process a SpaceShip-Asteroid collision;
}





int main()
{

    cout << "effective c++" << endl;
    return 0;
}